﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.Playables;
using TableProto;
using DynamicShadowProjector;

public class TimelineManager : MonoSingleton<TimelineManager>
{



    private const string dataPath = "game_timeline/timeline_data/timelinealldata";
    private const string timelineBasePath = "game_timeline/";
    private const string model_actorPath = "model/model_actor/";
    private const string model_storyPath = "model/model_story/";

    private const string gameScenePath = "model/model_main/";
    //private const string ximalayaScenePath = "story_himalaya";

    public static int juqingID;
    private GameObject go;
    private TimelineInfo info;


    private bool m_IsPlaying = false;
    private  GameObject scene;

    public bool IsPlaying
    {
        get
        {
            
            return m_IsPlaying;
        }
    }

    private bool directorComplete = false;


    private PlayableDirector m_CurrentDirector;

    private Dictionary<string, TimelineSingleData> dataDic = new Dictionary<string, TimelineSingleData>();
    private Dictionary<int, GameObject> timelineChache = new Dictionary<int, GameObject>();



    protected override void Init()
    {
        base.Init();

        InitializeData();
    }

    // 加载timeline数据
    private void InitializeData()
    {
        dataDic.Clear();

        Resource dataResource = ResourceManager.Instance.GetResource(dataPath, typeof(TextAsset), enResourceType.GameString, false, false);
        
        if (dataResource != null)
        {
            BinaryObject dataAsset = dataResource.m_content as BinaryObject;
            string result = System.Text.Encoding.UTF8.GetString(dataAsset.m_data);

            TimelineData tlData = new TimelineData();
            tlData = JsonUtility.FromJson<TimelineData>(result);

            for (int i = 0; i < tlData.timelineList.Count; i++)
            {
                TimelineSingleData singleData = tlData.timelineList[i];
                dataDic.Add(singleData.ID, singleData);
            }
        }
    }

    private TimelineSingleData GetTimelineData(string ID)
    {
        if (dataDic.ContainsKey(ID))
        {
            return dataDic[ID];
        }
        return null;
    }

    public void SetdirectorComplete()
    {
        if (m_CurrentDirector != null)
            m_CurrentDirector.time = m_CurrentDirector.duration;
    }

    private void Update()
    {
       
        if (m_CurrentDirector == null) return;
        if (m_IsPlaying && !directorComplete && m_CurrentDirector.state != PlayState.Playing)
        {
            directorComplete = true;
            m_IsPlaying = false;
            TimelineManager.Instance.transform.Find("Camera").gameObject.AddComponent<InputPhysicsRaycaster>();
            EventBus.Instance.BroadCastEvent(juqingID.ToString());
            //Debug.Log("XXXXXXXXXXXXXXXX" + juqingID);
            
            //Destroy(m_CurrentDirector.gameObject);
            m_CurrentDirector = null;
            
            
        }else {
            Destroy(TimelineManager.Instance.transform.Find("Camera").GetComponent<InputPhysicsRaycaster>());
        }
        
    }


    public float Play(int ID)
    {
       
        ResetScene();
        IntoPoor();
        juqingID = ID;
         info = TableProtoLoader.TimelineInfoDict[(uint)ID];
        go = GameObject.Find("timeline");
        Destroy(go);

        if (IsPlaying) return -1;
        
        TimelineSingleData data = GetTimelineData(ID.ToString());
        if (data == null)
        {
            Debug.LogError("Get timeline data faild!");
            return -1;
        }

        directorComplete = false;
        m_IsPlaying = true;
         go = new GameObject("timeline");
        //go.transform.SetParent(transform);
        //timelineChache.Add(ID, go);

        //scene =SceneObjManger.Instance.CreateSceneObject(info.scene_name);

        LoadScene();



        Resource playableRes = ResourceManager.Instance.GetResource(FileTools.CombinePath(timelineBasePath, data.ID), null, enResourceType.ScenePrefab, false, false);

        PlayableAsset playableAsset = playableRes.m_content as PlayableAsset;

        m_CurrentDirector = go.gameObject.AddComponent<PlayableDirector>();
        m_CurrentDirector.playableAsset = playableAsset;

        Dictionary<string, PlayableBinding> pbDict = new Dictionary<string, PlayableBinding>();

        IEnumerable<PlayableBinding> Bindings = playableAsset.outputs;

        foreach (PlayableBinding bindind in Bindings)
        {
            //Debug.Log("sourceBindingType" + ", sourceObject:" + bindind.sourceObject + ", streamName:" + bindind.streamName + ", streamType:" + bindind.streamType);
            pbDict.Add(bindind.streamName, bindind);
        }

        Dictionary<string, GameObject> cacheTest = new Dictionary<string, GameObject>();

        foreach (var temp in data.trackParentList)
        {
            GameObject obj = null;
            if (cacheTest.ContainsKey(temp.objName))
            {
                obj = cacheTest[temp.objName];
            }
            else
            {
                if (temp.storyName == "Commom")
                {
                    GameObject item = ResourceManager.Instance.GetResource(FileTools.CombinePath(model_storyPath, temp.objName), null, enResourceType.Prefab, false, false).m_content as GameObject;
                    //Debug.Log("XXXXXXXXXXXXXXXXXXXXX"+item.name);
                    obj = StoryGameObjectPool.Instance.GetPool(item);
                    cacheTest.Add(temp.objName, obj);
                }
                else if(temp.storyName == "Actor")
                {
                    GameObject item = ResourceManager.Instance.GetResource(FileTools.CombinePath(model_actorPath, temp.objName), null, enResourceType.Prefab, false, false).m_content as GameObject;
                    obj = StoryGameObjectPool.Instance.GetPool(item);
                    cacheTest.Add(temp.objName, obj);
                }
                else
                {
                    string url = temp.storyName + "/";
                    //Debug.Log(url + "XXXXXXXXXXXXXXXXXX" + temp.objName);
                    GameObject item = ResourceManager.Instance.GetResource(FileTools.CombinePath(url, temp.objName),  null, enResourceType.Prefab, false, false).m_content as GameObject;
                    obj = StoryGameObjectPool.Instance.GetPool(item);
                    cacheTest.Add(temp.objName, obj);

                }

            }

            obj.transform.SetParent(this.transform);
         obj.name = temp.objName;
            if (pbDict.ContainsKey(temp.trackName))
            {
                Object sourceObj = pbDict[temp.trackName].sourceObject;
                m_CurrentDirector.SetGenericBinding(sourceObj, obj);
                //Debug.LogError("obj:" + obj.name);
            }
            else
            {
                Debug.LogError("Get sourceObject falid!:trackname:" + temp.trackName);
            }
        }

        foreach (var temp in data.trackChildList)
        {
            if (cacheTest.ContainsKey(temp.parentName))
            {
                GameObject parentObj = cacheTest[temp.parentName];
                m_CurrentDirector.SetGenericBinding(pbDict[temp.trackName].sourceObject, FindChild(parentObj.transform, temp.objName));
            }
            else
            {
                Debug.Log("Parent is null:" + temp.parentName);
            }
        }

        GameObject Audio_Parent = null;
        if (data.trackAudioList.Count > 0)
        {
            GameObject item = ResourceManager.Instance.GetResource("model/model_story/Audio_Parent", null, enResourceType.ScenePrefab, false, false).m_content as GameObject;
            Audio_Parent = StoryGameObjectPool.Instance.GetPool(item);
            Audio_Parent.name=Audio_Parent.name.Replace("(Clone)", "");
            Audio_Parent.transform.SetParent(this.transform);
        }
        foreach (var temp in data.trackAudioList)
        {
                m_CurrentDirector.SetGenericBinding(pbDict[temp.trackName].sourceObject, Audio_Parent.transform.Find(temp.objName).GetComponent<AudioSource>());
        }

        // 设置阴影投射

        foreach (GameObject go in cacheTest.Values)
        {
            DrawTargetObject dt = go.GetComponent<DrawTargetObject>();
            if (dt != null)
            {
                string name = dt.GetActorName();
                if (cacheTest.ContainsKey(name))
                {
                    dt.target = cacheTest[name].transform;
                }
            }
        }

        m_CurrentDirector.Play();

        return (float)m_CurrentDirector.duration;
    }


    // 通过名字获取元素
    private GameObject FindChild(Transform Target, string ChildName)
    {
        Transform[] childs = Target.GetComponentsInChildren<Transform>(true);
        foreach (Transform go in childs)
        {
            if (go.name == ChildName)
                return go.gameObject;
        }

        return null;
    }

    public void ResetScene() {
		if (scene != null)
        	SceneObjManger.Instance.RecycleGameObject(scene);
    }

    //加载场景
    void LoadScene() {

        if (info.scene_name != "0")
        {
            if (info.scene_Tag != "Commom")
            {
                string url = info.scene_Tag + "/";
                GameObject item = ResourceManager.Instance.GetResource(FileTools.CombinePath(url, info.scene_name), null, enResourceType.ScenePrefab, false, false).m_content as GameObject;
                GameObject gamescene =StoryGameObjectPool.Instance.GetPool(item);
                gamescene.name = gamescene.name.Replace("(Clone)", "");
                gamescene.transform.SetParent(this.transform);
            }
            else
            {
                string url = gameScenePath;
                GameObject item= ResourceManager.Instance.GetResource(FileTools.CombinePath(url, info.scene_name), null, enResourceType.ScenePrefab, false, false).m_content as GameObject;
                GameObject gamescene = StoryGameObjectPool.Instance.GetPool(item);
                gamescene.name = gamescene.name.Replace("(Clone)", "");
                gamescene.transform.SetParent(this.transform);
            }
        }
    }

    //进入对象池
    void IntoPoor() {
     foreach(Transform child in this.transform ) {
            StoryGameObjectPool.Instance.IntoPool(child.gameObject);
     }
    }




}
